package com.tarena.lbs.marketing.controller;

import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.model.Result;
import com.tarena.lbs.base.protocol.pager.BasePageList;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.common.marketing.converter.CouponConverter;
import com.tarena.lbs.common.marketing.converter.UserReceiveCouponConverter;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.common.security.utils.LbsSecurityContenxt;
import com.tarena.lbs.marketing.event.CouponOutput;
import com.tarena.lbs.marketing.service.CouponService;
import com.tarena.lbs.pojo.marketing.bo.CouponBO;
import com.tarena.lbs.pojo.marketing.bo.UserReceiveCouponBO;
import com.tarena.lbs.pojo.marketing.param.CouponParam;
import com.tarena.lbs.pojo.marketing.param.UserReceiveCouponParam;
import com.tarena.lbs.pojo.marketing.query.CouponQuery;
import com.tarena.lbs.pojo.marketing.query.UserCouponCodeQuery;
import com.tarena.lbs.pojo.marketing.query.UserCouponQuery;
import com.tarena.lbs.pojo.marketing.vo.CouponVO;
import com.tarena.lbs.pojo.marketing.vo.UserReceiveCouponVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;

@RestController
@Slf4j
@EnableBinding(CouponOutput.class)
public class CouponController {
    @Autowired
    private CouponService couponService;
    //扫描com.tarena.lbs.*.marketing中 有转化器的bean对象
    @Autowired
    private CouponConverter couponConverter;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private CouponOutput couponOutput;

    //根据query条件 查询分页的优惠券列表
    @PostMapping("/admin/marketing/coupon/info/list")
    public Result<PageResult<CouponVO>> couponPage(@RequestBody CouponQuery query)
            throws BusinessException {
        //1 业务返回包装了total和list的对象
        BasePageList<CouponBO> bos= couponService.couponPage(query);
        //2 利用转化器解析返回voPage
        return new Result<>(couponConverter.assemblePageVOS(bos,query));
    }
    //后台新增优惠券
    @PostMapping("/admin/marketing/coupon/info/save")
    public Result<Void> couponSave(@RequestBody CouponParam couponParam) throws BusinessException, ParseException {
        log.info("新增优惠券入参:{}",couponParam);
        CouponBO bo=new CouponBO();
        //转成BO 交给业务处理 补全数据
        BeanUtils.copyProperties(couponParam,bo);
        //手动补充 转化startDate和endDate的字符串 为date类型
        bo.setStartDate(DateUtils.parseDate(couponParam.getStartDate(),"yyyy-MM-dd HH:mm:ss"));
        bo.setEndDate(DateUtils.parseDate(couponParam.getEndDate(),"yyyy-MM-dd HH:mm:ss"));
        couponService.couponSave(bo);
        return Result.success();
    }
    //查询优惠券详情
    @GetMapping("/admin/marketing/coupon/info/detail/{id}")
    public Result<CouponVO> couponDetail(@PathVariable Integer id) throws BusinessException{
        CouponBO bo=couponService.couponDetail(id);
        CouponVO vo = couponConverter.bo2vo(bo);
        return new Result<>(vo);
    }
    //优惠价
    @PostMapping("/marketing/user/receive/save")
    public Result<Void> userReceiveSave(@RequestBody UserReceiveCouponParam param) throws BusinessException{
        //组织消息发送,考虑发送消息数据 覆盖业务(准确) 只覆盖业务(精简)
        UserPrinciple userPrinciple = LbsSecurityContenxt.getLoginToken();
        Asserts.isTrue(userPrinciple==null,new BusinessException("101","用户认证解析失败"));
        //1. 思考 初始化redis库存 key怎么设计的 要和业务绑定 couponId
        String couponStockKey="coupon:stock:"+param.getCouponId();
        //2. decr coupon:stock:10
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        Long decrement = opsForValue.decrement(couponStockKey);
        //3. 判断decrement返回结果是否<0 异常结束
        Asserts.isTrue(decrement<0,new BusinessException("111","您领取优惠券失败"));
        param.setUserId(userPrinciple.getId());
        //消息体
        Message<UserReceiveCouponParam> message = MessageBuilder.withPayload(param).build();
        //当前系统中定义的 output通道
        couponOutput.userGetCouponOutput().send(message);
        return Result.success();
    }

    @Autowired
    private UserReceiveCouponConverter userReceiveCouponConverter;
    //查询某个用户的优惠券领取记录
    @PostMapping("/marketing/user/receive/list")
    public Result<PageResult<UserReceiveCouponVO>> userReceiveList(@RequestBody UserCouponQuery query)
            throws BusinessException{
        BasePageList<UserReceiveCouponBO> boPages=couponService.userReceivePage(query);
        //2 利用转化器解析返回voPage
        PageResult<UserReceiveCouponVO> userCouponPage = userReceiveCouponConverter.assemblePageVOS(boPages, query);
        return new Result<>(userCouponPage);
    }
    @PostMapping("/marketing/user/receive/detail")
    public Result<UserReceiveCouponVO> userCouponDetail(@RequestBody UserCouponCodeQuery query)
            throws BusinessException{
        UserReceiveCouponBO bo=couponService.userReceiveDetail(query);
        UserReceiveCouponVO vo = userReceiveCouponConverter.bo2vo(bo);
        return new Result<>(vo);
    }
}
